/* dump.c */

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>

#include "dump.h"

static FILE *dump_file;

/**
 * Set dump output file.
 *
 * Use NULL for no output, or "-" for stdout.
 */
void dump_set_output(const char *file)
{
  // close old dump file
  if (dump_file && dump_file != stdout)
    fclose(dump_file);

  // if file is NULL, suppress dumping
  if (! file) {
    dump_file = NULL;
    return;
  }

  // if file is "-", use stdout
  if (file[0] == '-' && file[1] == '\0') {
    dump_file = stdout;
    return;
  }

  // any other file is opened, falling back to stdout
  dump_file = fopen(file, "a");
  if (! dump_file)
    dump_file = stdout;
}

/**
 * Dump a formatted message.
 */
void dump_msg(const char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  if (dump_file)
    vfprintf(dump_file, fmt, ap);
  va_end(ap);
}

/**
 * Dump data.
 */
void dump_data(unsigned int show_off, void *data, unsigned int len)
{
  unsigned char *p = data;
  char line[17];
  int i;
  unsigned int off;
  int jump;

  if (! dump_file)
    return;

  //fprintf(dump_file, "--> show_off=%d (0x%x), len=%d (0x%x)\n", show_off, show_off, len, len);

  jump = show_off % 16;
  off = 0;
  while (off < len) {
    fprintf(dump_file, "%08x |", (off + show_off) & ~0xf);

    for (i = 0; i < jump; i++) {
      if (i == 8) fprintf(dump_file, " ");
      fprintf(dump_file, "   ");
      line[i] = ' ';
    }

    for (i = jump; i < 16; i++) {
      unsigned int ch = p[off + i - jump];
      if (i == 8) fprintf(dump_file, " ");
      if (off + i < len) {
	fprintf(dump_file, " %02x", ch);
	line[i] = (ch >= 32 && ch < 127) ? ch : '.';
      } else {
	fprintf(dump_file, "   ");
	line[i] = ' ';
      }
    }
    line[i] = 0;
    fprintf(dump_file, " | %s\n", line);
    off += 16 - jump;
    jump = 0;
  }
}
